﻿using System;
using System.Windows.Forms;
using System.Drawing;
using System.ComponentModel;	
using System.IO;

namespace Tomasulo
{
    enum TomasuloType
    {
        Add,
        Sub,
        Mul,
        Div,
    };
    class st
    {
        public int station1;
        public int source1;
        public double value1;
        public int station2;
        public int source2;
        public double value2;
        public int state;
        public TomasuloType type;
        public int dest;
        public double result;
        public bool islock;		//新添加，用于实现写后读相关
    };

    class Adder
    {
        public st[] str;	//A1,A2,A3
        public Adder()
        {
            str = new st[3];
            for (int i = 0; i < 3; i++)
                str[i] = new st();
        }
    };

    class Multiplier
    {
        public st[] str;	//M1,M2
        public Multiplier()
        {
            str = new st[2];
            for (int i = 0; i < 2; i++)
                str[i] = new st();
        }
    };

    //浮点通用寄存器
    class Reg
    {
        public bool busy;			//busy = true表示将要被写入，不可使用
        public bool valid;
        public int station;
        public int value;
    };

    //浮点先行读数站
    class Prereg
    {
        public int value;
        public int order;		//本应存到哪个浮点通用寄存器
        public bool valid;
    };
    //浮点先行操作站
    class Operation
    {
        public bool valid;
        public TomasuloType type;
        public int source1;
        public int source2;
        public int source3;
    };

    //先行指令缓冲栈
    /*struct Preop
    {
        int num;
        char ops[10][50];	//缓冲10条指令
    }preop;*/

    //浮点后行写数站
    class Writeback
    {
        public int value;
        public int order;		//写到主存的位置
        public int station;
        public bool valid;
    };

    class Apparatus
    {

        public int Timer;
        public int opnum;	//浮点操作总数，用于先行操作站
        public int[] memory;
        public Adder adder;
        public Multiplier muler;
        public Reg[] reg;
        public Prereg[] pre;
        public Operation[] operation;
        public Writeback[] writeback;
        public StreamReader reader;
        public FileStream fs;
        bool run;
        bool toend;
        public Apparatus()
        {
            memory = new int[4096];
            adder = new Adder();
            muler = new Multiplier();
            reg = new Reg[8];
            pre = new Prereg[6];
            operation = new Operation[10];
            writeback = new Writeback[6];
            for (int i = 0; i < 8; i++)
            {
                reg[i] = new Reg();
                reg[i].busy = false;
                reg[i].station = -1;
                reg[i].valid = true;
                reg[i].value = 0;

            }
            //reg[1].value = 1;
            //reg[5].value = 5;
            //reg[6].value = 6;
            for (int i = 0; i < 6; i++)
            {
                pre[i] = new Prereg();
                pre[i].valid = false;
                pre[i].value = 0;

            }
            for (int i = 0; i < 6; i++)
            {
                writeback[i] = new Writeback();
                writeback[i].valid = false;
                writeback[i].value = 0;
                writeback[i].station = -1;
            }
            for (int i = 0; i < 10; i++)
            {
                operation[i] = new Operation();
                operation[i].valid = false;
            }
            for (int i = 0; i < 3; i++)
            {
                adder.str[i].state = 0;		//表示未被占用
                adder.str[i].station1 = -1;	//表示默认直接通过寄存器读取
                adder.str[i].station2 = -1;
                adder.str[i].islock = false;
                adder.str[i].value1 = -10000;
                adder.str[i].value2 = -10000;
            }
            for (int i = 0; i < 2; i++)
            {
                muler.str[i].state = 0;
                muler.str[i].station1 = -1;
                muler.str[i].station2 = -1;
                muler.str[i].islock = false;
                muler.str[i].value1 = -10000;
                muler.str[i].value2 = -10000;
            }

            //	preop.num = 0;

            string file = "../../order.txt";
            fs = new FileStream(file, FileMode.Open);
            reader = new StreamReader(fs);

            run = true;
        }

        public bool getEnd()
        {
            return toend;
        }

        public bool getRun()
        {
            return run;
        }

        private void update()
        {
            int i = 0;
            while (i + 1 < opnum)			//去掉此项，操作站更新
            {
                operation[i].source1 = operation[i + 1].source1;
                operation[i].source2 = operation[i + 1].source2;
                operation[i].source3 = operation[i + 1].source3;
                operation[i].type = operation[i + 1].type;
                operation[i].valid = operation[i + 1].valid;
                i++;
            }
            operation[i].valid = false;
            opnum--;
        }

        public void action()
        {
            string order = null;
            int i, j, k;
            Timer++;
            if (run == true)
            {
                order = reader.ReadLine();
                if (String.Compare(order, "END") == 0)
                    run = false;
            }
            if (run == true)
            {
                string temp;
                string str = order;
                temp = str.Substring(0, str.IndexOf(" "));
                if (String.Compare(temp, "ADDD") == 0 || String.Compare(temp, "SUBD") == 0 || String.Compare(temp, "MULD") == 0 || String.Compare(temp, "DIVD") == 0)
                {
                    if (String.Compare(temp, "ADDD") == 0)
                        operation[opnum].type = TomasuloType.Add;
                    else if (String.Compare(temp, "SUBD") == 0)
                        operation[opnum].type = TomasuloType.Sub;
                    else if (String.Compare(temp, "MULD") == 0)
                        operation[opnum].type = TomasuloType.Mul;
                    else if (String.Compare(temp, "DIVD") == 0)
                        operation[opnum].type = TomasuloType.Div;
                    str = str.Substring(str.IndexOf(" ") + 1);
                    temp = str.Substring(1, str.IndexOf(" "));
                    i = int.Parse(temp);
                    str = str.Substring(str.IndexOf(" ") + 1);
                    temp = str.Substring(1, str.IndexOf(" "));
                    j = int.Parse(temp);
                    str = str.Substring(str.IndexOf(" ") + 1);
                    temp = str.Substring(1);
                    k = int.Parse(temp);
                    operation[opnum].valid = true;		//将浮点操作指令存入栈
                    operation[opnum].source1 = i;
                    operation[opnum].source2 = j;
                    operation[opnum].source3 = k;
                    opnum++;
                }
                else if (String.Compare(temp, "ST") == 0)
                {
                    str = str.Substring(str.IndexOf(" ") + 1);
                    temp = str.Substring(1, str.IndexOf(" "));
                    i = int.Parse(temp);
                    str = str.Substring(str.IndexOf(" ") + 1);
                    temp = str.Substring(0);
                    j = int.Parse(temp);
                    for (k = 0; k < 6; k++)
                    {
                        if (writeback[k].valid == false)
                        {
                            if (reg[i].busy == false)
                            {
                                writeback[k].value = reg[i].value;
                                writeback[k].order = j;
                                writeback[k].station = i;
                                writeback[k].valid = true;
                                break;
                            }
                            else
                            {
                                writeback[k].order = j;
                                writeback[k].station = reg[i].station;
                                writeback[k].valid = true;
                                break;
                            }
                        }
                    }
                }
                else if (String.Compare(temp, "LD") == 0)
                {
                    str = str.Substring(str.IndexOf(" ") + 1);
                    temp = str.Substring(1, str.IndexOf(" "));
                    i = int.Parse(temp);
                    str = str.Substring(str.IndexOf(" ") + 1);
                    temp = str.Substring(0);
                    j = int.Parse(temp);
                    for (k = 0; k < 6; k++)		//暂存在浮点先行读数站
                    {
                        if (pre[k].valid == false)
                        {
                            pre[k].value = memory[j];
                            pre[k].order = i;		//应存到的浮点通用寄存器
                            pre[k].valid = true;
                            break;
                        }
                    }
                }
                else
                {
                    return;
                }
            }
            /*
            /*下面进行各个功能部件的操作
            /*
            /*需要进行操作的功能部件：
            /*浮点先行操作站（如果有指令，加法器/乘法器有空间，则将其载入）
            /*浮点先行读数站（每个读入的数据保留一个周期后，存入浮点通用寄存器或直接存入加法器/乘法器）
            /*浮点后行写数站（保留一个周期后，写回浮点通用寄存器（注意不能发生数据相关））
            /*浮点通用寄存器（可能更新站号、忙位）
            /*加法器/乘法器（内部流水线更新，完成后根据站号判断应该将结果写到哪里）
            /*控制位需要更新
            *************************************/

            //for(i = 0; i < opnum; i++)
            //					cout << "operation" << i << " is " << operation[i].type << endl;

            //实现浮点先行操作站

            if (opnum != 0 && operation[0].valid == true)
            {
                int op1, op2, op3;
                op1 = operation[0].source1;
                op2 = operation[0].source2;
                op3 = operation[0].source3;

                //检查是加减还是乘除
                if (operation[0].type == TomasuloType.Add || operation[0].type == TomasuloType.Sub)
                {
                    if (adder.str[0].state == 0)		//保存站可用
                    {
                        //更新索引
                        adder.str[0].state = 1;
                        if (operation[0].type == TomasuloType.Add)
                            adder.str[0].type = TomasuloType.Add;
                        else
                            adder.str[0].type = TomasuloType.Sub;
                        adder.str[0].source1 = op2;
                        adder.str[0].source2 = op3;
                        adder.str[0].dest = op1;

                        for (i = 0; i < 6; i++)
                        {
                            if (pre[i].order == op2 && pre[i].valid == true)
                            {
                                adder.str[0].station1 = i;
                            }
                            else if (pre[i].order == op3 && pre[i].valid == true)
                            {
                                adder.str[0].station2 = i;
                            }
                            else if (pre[i].order == op1 && pre[i].valid == true)		//防止“写-写”数据相关
                            {
                                pre[i].valid = false;
                            }
                        }

                        if (reg[op2].busy || reg[op3].busy)				//写后读相关
                        {
                            if (reg[op2].busy)
                            {
                                adder.str[0].station1 = reg[op2].station;
                            }
                            if (reg[op3].busy)
                            {
                                adder.str[0].station2 = reg[op3].station;
                            }
                            reg[op1].busy = true;
                            reg[op1].station = 10;
                            update();
                            goto end1;
                        }

                        reg[op1].busy = true;		//置忙位
                        reg[op1].station = 10;		//保存站号
                        update();
                    }
                    else if (adder.str[1].state == 0)
                    {
                        //更新索引
                        adder.str[1].state = 1;
                        if (operation[0].type == TomasuloType.Add)
                            adder.str[1].type = TomasuloType.Add;
                        else
                            adder.str[1].type = TomasuloType.Sub;
                        adder.str[1].source1 = op2;
                        adder.str[1].source2 = op3;
                        adder.str[1].dest = op1;

                        for (i = 0; i < 6; i++)
                        {
                            if (pre[i].order == op2 && pre[i].valid == true)
                            {
                                adder.str[1].station1 = i;
                            }
                            else if (pre[i].order == op3 && pre[i].valid == true)
                            {
                                adder.str[1].station2 = i;
                            }
                            else if (pre[i].order == op1 && pre[i].valid == true)		//防止“写-写”数据相关
                            {
                                pre[i].valid = false;
                            }
                        }

                        if (reg[op2].busy || reg[op3].busy)
                        {
                            if (reg[op2].busy)
                            {
                                adder.str[1].station1 = reg[op2].station;
                            }
                            if (reg[op3].busy)
                            {
                                adder.str[1].station2 = reg[op3].station;
                            }
                            reg[op1].busy = true;
                            reg[op1].station = 11;
                            update();
                            goto end1;
                        }

                        reg[op1].busy = true;
                        reg[op1].station = 11;
                        update();
                    }
                    else if (adder.str[2].state == 0)
                    {
                        //更新索引
                        adder.str[2].state = 1;
                        if (operation[0].type == TomasuloType.Add)
                            adder.str[2].type = TomasuloType.Add;
                        else
                            adder.str[2].type = TomasuloType.Sub;
                        adder.str[2].source1 = op2;
                        adder.str[2].source2 = op3;
                        adder.str[2].dest = op1;

                        for (i = 0; i < 6; i++)
                        {
                            if (pre[i].order == op2 && pre[i].valid == true)
                            {
                                adder.str[2].station1 = i;
                            }
                            else if (pre[i].order == op3 && pre[i].valid == true)
                            {
                                adder.str[2].station2 = i;
                            }
                            else if (pre[i].order == op1 && pre[i].valid == true)		//防止“写-写”数据相关
                            {
                                pre[i].valid = false;
                            }
                        }

                        if (reg[op2].busy || reg[op3].busy)
                        {
                            if (reg[op2].busy)
                            {
                                adder.str[2].station1 = reg[op2].station;
                            }
                            if (reg[op3].busy)
                            {
                                adder.str[2].station2 = reg[op3].station;
                            }
                            reg[op1].busy = true;
                            reg[op1].station = 12;
                            update();
                            goto end1;
                        }

                        reg[op1].busy = true;
                        reg[op1].station = 12;
                        update();
                    }
                    else
                        goto end1;		//等待
                }
                else if (operation[0].type == TomasuloType.Mul || operation[0].type == TomasuloType.Div)
                {
                    if (muler.str[0].state == 0)
                    {
                        //更新索引
                        muler.str[0].state = 1;
                        if (operation[0].type == TomasuloType.Mul)
                            muler.str[0].type = TomasuloType.Mul;
                        else
                            muler.str[0].type = TomasuloType.Div;
                        muler.str[0].source1 = op2;
                        muler.str[0].source2 = op3;
                        muler.str[0].dest = op1;

                        for (i = 0; i < 6; i++)
                        {
                            if (pre[i].order == op2 && pre[i].valid == true)
                            {
                                muler.str[0].station1 = i;
                            }
                            else if (pre[i].order == op3 && pre[i].valid == true)
                            {
                                muler.str[0].station2 = i;
                            }
                            else if (pre[i].order == op1 && pre[i].valid == true)		//防止“写-写”数据相关
                            {
                                pre[i].valid = false;
                            }
                        }

                        if (reg[op2].busy || reg[op3].busy)
                        {
                            if (reg[op2].busy)
                            {
                                muler.str[0].station1 = reg[op2].station;
                            }
                            if (reg[op3].busy)
                            {
                                muler.str[0].station2 = reg[op3].station;
                            }
                            reg[op1].busy = true;
                            reg[op1].station = 8;
                            update();
                            goto end1;
                        }

                        reg[op1].busy = true;		//置忙位
                        reg[op1].station = 8;
                        update();

                    }
                    else if (muler.str[1].state == 0)
                    {
                        //更新索引
                        muler.str[1].state = 1;
                        if (operation[0].type == TomasuloType.Mul)
                            muler.str[1].type = TomasuloType.Mul;
                        else
                            muler.str[1].type = TomasuloType.Div;
                        muler.str[1].source1 = op2;
                        muler.str[1].source2 = op3;
                        muler.str[1].dest = op1;

                        for (i = 0; i < 6; i++)
                        {
                            if (pre[i].order == op2 && pre[i].valid == true)
                            {
                                muler.str[1].station1 = i;
                            }
                            else if (pre[i].order == op3 && pre[i].valid == true)
                            {
                                muler.str[1].station2 = i;
                            }
                            else if (pre[i].order == op1 && pre[i].valid == true)		//防止“写-写”数据相关
                            {
                                pre[i].valid = false;
                            }
                        }

                        if (reg[op2].busy || reg[op3].busy)
                        {
                            if (reg[op2].busy)
                            {
                                muler.str[1].station1 = reg[op2].station;
                            }
                            if (reg[op3].busy)
                            {
                                muler.str[1].station2 = reg[op3].station;
                            }
                            reg[op1].busy = true;
                            reg[op1].station = 9;
                            update();
                            goto end1;
                        }

                        reg[op1].busy = true;		//置忙位
                        reg[op1].station = 9;
                        update();
                    }
                    //else
                    //;		//等待

                }
            }

        end1:

            //实现浮点先行读数站

            for (i = 0; i < 6; i++)
            {
                if (pre[i].valid == true)
                {
                    reg[pre[i].order].value = pre[i].value;			//写到寄存器
                    pre[i].valid = false;
                }
            }


            //实现浮点后行写数站

            for (i = 0; i < 6; i++)
            {
                if (writeback[i].valid == true && writeback[i].station < 7)
                {
                    memory[writeback[i].order] = writeback[i].value;
                    writeback[i].valid = false;
                }
            }


            //实现浮点通用寄存器

            /*		for(i = 0; i < 6; i++)
                    {
                        if(writeback[i].value > 10000)
                        {
                            if(reg[writeback[i].reg].busy == false)
                            {
                                writeback[i].value = reg[writeback[i].reg].value;
                                memory[writeback[i].order] = writeback[i].value;
                                writeback[i].valid = false;
                            }
                        }
                    }*/

            //实现加/减法器
            for (i = 0; i < 3; i++)
            {
                if (adder.str[i].state != 0)
                {
                    if (adder.str[i].state == 1)			//刚刚载入
                    {
                        if (adder.str[i].type == TomasuloType.Add)		//加法
                        {
                            //					cout << "Adding" << endl;
                            int result, a = 0, b = 0;
                            //					cout << "Source1=reg" << adder.str[i].source1 << endl;
                            //					cout << "Source2=reg" << adder.str[i].source2 << endl;
                            if (adder.str[i].station1 == -1)						//先不考虑加法器可能要用乘法器的结果
                                a = reg[adder.str[i].source1].value;
                            else if (adder.str[i].station1 < 7)
                                a = pre[adder.str[i].station1].value;
                            else if (adder.str[i].value1 != -10000)
                                a = (int)adder.str[i].value1;
                            else
                                adder.str[i].islock = true;


                            if (adder.str[i].station2 == -1)
                                b = reg[adder.str[i].source2].value;
                            else if (adder.str[i].station2 < 7)
                                b = pre[adder.str[i].station2].value;
                            else if (adder.str[i].value2 != -10000)
                                b = (int)adder.str[i].value2;
                            else
                                adder.str[i].islock = true;

                            if (adder.str[i].islock == false)
                            {
                                result = a + b;
                                adder.str[i].result = result;
                                //							cout << "a=" << a << " b=" << b << endl;
                            }
                        }
                        else	//减法
                        {
                            int result, a = 0, b = 0;
                            if (adder.str[i].station1 == -1)						//先不考虑加法器可能要用乘法器的结果
                                a = reg[adder.str[i].source1].value;
                            else if (adder.str[i].station1 < 7)
                                a = pre[adder.str[i].station1].value;
                            else if (adder.str[i].value1 != -10000)
                                a = (int)adder.str[i].value1;
                            else
                                adder.str[i].islock = true;

                            if (adder.str[i].station2 == -1)
                                b = reg[adder.str[i].source2].value;
                            else if (adder.str[i].station2 < 7)
                                b = pre[adder.str[i].station2].value;
                            else if (adder.str[i].value2 != -10000)
                                b = (int)adder.str[i].value2;
                            else
                                adder.str[i].islock = true;

                            if (adder.str[i].islock == false)
                            {
                                result = a - b;
                                adder.str[i].result = result;
                            }
                        }
                    }
                    else if (adder.str[i].state == 3)			//可能出现“读后写”数据相关（删掉此句，改为直接写回要读的地方（加法器或乘法器中））
                        adder.str[i].state--;

                    //			cout << "Result of adder" << i << " is " << adder.str[i].result << endl;
                    if (adder.str[i].islock == false)
                        adder.str[i].state++;

                    if (adder.str[i].state == 3)
                    {
                        //写回（未考虑写回到其他站的情况）
                        if (reg[adder.str[i].dest].station == i + 10)
                        {
                            if (reg[adder.str[i].dest].busy == true)
                                reg[adder.str[i].dest].busy = false;
                            reg[adder.str[i].dest].value = (int)adder.str[i].result;
                        }
                        adder.str[i].state = 0;
                        for (j = 0; j < 3; j++)
                        {
                            if (j != i && adder.str[j].station1 == i + 10)
                            {
                                adder.str[j].station1 = -1;
                                adder.str[j].value1 = adder.str[i].result;
                            }
                            if (j != i && adder.str[j].station2 == i + 10)
                            {
                                adder.str[j].station2 = -1;
                                adder.str[j].value2 = adder.str[i].result;
                            }
                            if (adder.str[j].station1 < 7 && adder.str[j].station2 < 7)
                                adder.str[j].islock = false;
                        }
                        for (j = 0; j < 2; j++)
                        {
                            if (muler.str[j].station1 == i + 10)
                            {
                                muler.str[j].station1 = -1;
                                muler.str[j].value1 = adder.str[i].result;
                            }
                            if (muler.str[j].station2 == i + 10)
                            {
                                muler.str[j].station2 = -1;
                                muler.str[j].value2 = adder.str[i].result;
                            }
                            if (muler.str[j].station1 < 7 && muler.str[j].station2 < 7)
                                muler.str[j].islock = false;
                        }
                        for (j = 0; j < 6; j++)
                        {
                            if (writeback[j].valid == true && writeback[j].station == i + 10)
                            {
                                writeback[j].value = (int)adder.str[i].result;
                                writeback[j].station = -1;
                            }
                        }
                        adder.str[i].value1 = -10000;
                        adder.str[i].value2 = -10000;
                        adder.str[i].station1 = -1;
                        adder.str[i].station2 = -1;
                        //				cout << adder.str[i].result << endl;
                    }
                }

            }



            //实现乘/除法器
            for (i = 0; i < 2; i++)
            {
                if (muler.str[i].state != 0)
                {
                    if (muler.str[i].state == 1)			//刚刚载入
                    {
                        if (muler.str[i].type == TomasuloType.Mul)		//乘法
                        {
                            int result, a = 0, b = 0;
                            if (muler.str[i].station1 == -1)						//先不考虑乘法器可能要用加法器的结果
                                a = reg[muler.str[i].source1].value;
                            else if (muler.str[i].station1 < 7)
                                a = pre[muler.str[i].station1].value;
                            else if (muler.str[i].value1 != -10000)
                                a = (int)muler.str[i].value1;
                            else
                                muler.str[i].islock = true;

                            if (muler.str[i].station2 == -1)
                                b = reg[muler.str[i].source2].value;
                            else if (muler.str[i].station2 < 7)
                                b = pre[muler.str[i].station2].value;
                            else if (muler.str[i].value2 != -10000)
                                b = (int)muler.str[i].value2;
                            else
                                muler.str[i].islock = true;

                            if (muler.str[i].islock == false)
                            {
                                result = a * b;
                                muler.str[i].result = result;
                            }
                        }
                        else	//除法
                        {
                            int result, a = 0, b = 1;
                            if (muler.str[i].station1 == -1)						//先不考虑乘法器可能要用加法器的结果
                                a = reg[muler.str[i].source1].value;
                            else if (muler.str[i].station1 < 7)
                                a = pre[muler.str[i].station1].value;
                            else if (muler.str[i].value1 != -10000)
                                a = (int)muler.str[i].value1;
                            else
                                muler.str[i].islock = true;

                            if (muler.str[i].station2 == -1)
                                b = reg[muler.str[i].source2].value;
                            else if (muler.str[i].station2 < 7)
                                b = pre[muler.str[i].station2].value;
                            else if (muler.str[i].value2 != -10000)
                                b = (int)muler.str[i].value2;
                            else
                                muler.str[i].islock = true;
                            if (muler.str[i].islock == false)
                            {
                                result = a / b;
                                muler.str[i].result = result;
                            }
                        }
                    }
                    else if ((muler.str[i].state == 11 && muler.str[i].type == TomasuloType.Mul) || (muler.str[i].state == 41 && muler.str[i].type == TomasuloType.Div))
                        muler.str[i].state--;

                    if (muler.str[i].islock == false)
                        muler.str[i].state++;

                    if ((muler.str[i].state == 11 && muler.str[i].type == TomasuloType.Mul) || (muler.str[i].state == 41 && muler.str[i].type == TomasuloType.Div))
                    {
                        //写回（未考虑写回到其他站的情况）
                        if (reg[muler.str[i].dest].station == i + 8)
                        {
                            if (reg[muler.str[i].dest].busy == true)
                                reg[muler.str[i].dest].busy = false;
                            reg[muler.str[i].dest].value = (int)muler.str[i].result;
                        }
                        muler.str[i].state = 0;
                        for (j = 0; j < 3; j++)
                        {
                            if (adder.str[j].station1 == i + 8)
                            {
                                adder.str[j].station1 = -1;
                                adder.str[j].value1 = muler.str[i].result;
                            }
                            if (adder.str[j].station2 == i + 8)
                            {
                                adder.str[j].station2 = -1;
                                adder.str[j].value2 = muler.str[i].result;
                            }
                            if (adder.str[j].station1 < 7 && adder.str[j].station2 < 7)
                                adder.str[j].islock = false;
                        }
                        for (j = 0; j < 2; j++)
                        {
                            if (j != i && muler.str[j].station1 == i + 8)
                            {
                                muler.str[j].station1 = -1;
                                muler.str[j].value1 = muler.str[i].result;
                            }
                            if (j != i && muler.str[j].station2 == i + 8)
                            {
                                muler.str[j].station2 = -1;
                                muler.str[j].value2 = muler.str[i].result;
                            }
                            if (muler.str[j].station1 < 7 && muler.str[j].station2 < 7)
                                muler.str[j].islock = false;
                        }
                        for (j = 0; j < 6; j++)
                        {
                            if (writeback[j].valid == true && writeback[j].station == i + 8)
                            {
                                writeback[j].value = (int)muler.str[i].result;
                                writeback[j].station = -1;
                            }
                        }
                        muler.str[i].value1 = -10000;
                        muler.str[i].value2 = -10000;
                        muler.str[i].station1 = -1;
                        muler.str[i].station2 = -1;
                    }
                }
            }

            //判断是否结束
            if (run == false)
            {
                toend = true;
                for (j = 0; j < 3; j++)
                {
                    if (adder.str[j].state != 0)
                        toend = false;
                }
                for (j = 0; j < 2; j++)
                {
                    if (muler.str[j].state != 0)
                        toend = false;
                }
                for (j = 0; j < 6; j++)
                {
                    if (pre[j].valid == true || writeback[j].valid == true)
                    {
                        toend = false;
                    }
                }
                if (opnum != 0)
                    toend = false;
            }
        }
    };
    class GUIDialog : Form
    {
        private DataGridView regDataGridView = new DataGridView();
        private DataGridView istrDataGridView = new DataGridView();
        private DataGridView memDataGridView = new DataGridView();
        private DataGridView addStDataGridView = new DataGridView();
        private DataGridView mulStDataGridView = new DataGridView();
        private DataGridView preRegDataGridView = new DataGridView();
        private DataGridView afterRegDataGridView = new DataGridView();
        private Button startButton = new Button();
        private Button cleanButton = new Button();
        private Button searchButton = new Button();
        private Button addButton = new Button();
        private RadioButton chooseButton1 = new RadioButton();
        private RadioButton chooseButton2 = new RadioButton();
        private Label label1 = new Label();
        private Label label2 = new Label();
        private Label state = new Label();
        private Panel choosePanel = new Panel();
        private Apparatus app = new Apparatus();
        private bool step = true;

        public GUIDialog()
        {
            this.Load += new EventHandler(GUIDialog_Load);
        }
        private void GUIDialog_Load(System.Object sender, System.EventArgs e)
        {
            Setup();
        }

        private void dataGridViewLayout(DataGridView dataGridView, int x, int y, int width, int i, int j)
        {
            j++;
            dataGridView.ColumnCount = i;
            dataGridView.RowCount = j;
            dataGridView.Location = new Point(x, y);
            dataGridView.Size = new Size(width * i, (int)(22.5 * j));
            this.Controls.Add(dataGridView);
            dataGridView.ColumnHeadersDefaultCellStyle.BackColor = Color.Navy;
            dataGridView.ColumnHeadersDefaultCellStyle.ForeColor = Color.White;
            dataGridView.AllowUserToAddRows = false;
            dataGridView.GridColor = Color.Black;
            dataGridView.RowHeadersVisible = false;
            for (int k = 0; k < i; k++)
                dataGridView.Columns[k].Width = width;
            if (j == 2)
                return;
            for (int k = 0; k < j - 1; k++)
                dataGridView[0, k].Value = k;
        }
        public void setDataGridViewName(DataGridView dataGridView, string[] str, int n)
        {
            for (int i = 0; i < n; i++)
                dataGridView.Columns[i].Name = str[i];
        }
        private void update()
        {
            int i;
            for (i = 0; i < 10; i++)
            {
                istrDataGridView[1, i].Value = app.operation[i].type;
                istrDataGridView[2, i].Value = app.operation[i].source1;
                istrDataGridView[3, i].Value = app.operation[i].source2;
                istrDataGridView[4, i].Value = app.operation[i].source3;
                istrDataGridView[5, i].Value = app.operation[i].valid;
            }
            for (i = 0; i < 8; i++)
            {
                regDataGridView[1, i].Value = app.reg[i].busy;
                regDataGridView[2, i].Value = app.reg[i].station;
                regDataGridView[3, i].Value = app.reg[i].value;
                regDataGridView[4, i].Value = app.reg[i].valid;
            }
            for (i = 0; i < 6; i++)
            {
                preRegDataGridView[1, i].Value = app.pre[i].order;
                preRegDataGridView[2, i].Value = app.pre[i].value;
                preRegDataGridView[3, i].Value = app.pre[i].valid;
            }
            for (i = 0; i < 6; i++)
            {
                afterRegDataGridView[1, i].Value = app.writeback[i].order;
                afterRegDataGridView[2, i].Value = app.writeback[i].value;
                afterRegDataGridView[3, i].Value = app.writeback[i].station;
                afterRegDataGridView[4, i].Value = app.writeback[i].valid;
            }
            for (i = 0; i < 3; i++)
            {
                addStDataGridView[1, i].Value = app.adder.str[i].station1;
                addStDataGridView[2, i].Value = app.adder.str[i].source1;
                addStDataGridView[3, i].Value = app.adder.str[i].value1;
                addStDataGridView[4, i].Value = app.adder.str[i].station2;
                addStDataGridView[5, i].Value = app.adder.str[i].source2;
                addStDataGridView[6, i].Value = app.adder.str[i].value2;
                addStDataGridView[7, i].Value = app.adder.str[i].state;
                addStDataGridView[8, i].Value = app.adder.str[i].type;
                addStDataGridView[9, i].Value = app.adder.str[i].result;
            }
            for (i = 0; i < 2; i++)
            {
                mulStDataGridView[1, i].Value = app.muler.str[i].station1;
                mulStDataGridView[2, i].Value = app.muler.str[i].source1;
                mulStDataGridView[3, i].Value = app.muler.str[i].value1;
                mulStDataGridView[4, i].Value = app.muler.str[i].station2;
                mulStDataGridView[5, i].Value = app.muler.str[i].source2;
                mulStDataGridView[6, i].Value = app.muler.str[i].value2;
                mulStDataGridView[7, i].Value = app.muler.str[i].state;
                mulStDataGridView[8, i].Value = app.muler.str[i].type;
                mulStDataGridView[9, i].Value = app.muler.str[i].result;
            }
        }
        private void startButton_Click(object sender, EventArgs e)
        {
            while (true)
            {
                app.action();
                if (app.getEnd() == true && app.getRun() == false)
                {
                    state.Text = "Timer:End";
                    clean();
                    break;
                }
                else
                    state.Text = "Timer:" + app.Timer;
                update();
                if (step == false)
                    break;
            }
        }
        private void clean()
        {
            app.reader.Close();
            app.fs.Close();
            app = new Apparatus();
        }
        private void cleanButton_Click(object sender, EventArgs e)
        {
            state.Text = "Timer:End";
            clean();
        }
        private void chooseButton_Click(object sender, EventArgs e)
        {
            foreach (RadioButton r in choosePanel.Controls)
            {
                if (r.Checked)
                {
                    if (r == chooseButton1)
                    {
                        step = true;
                    }
                    else
                    {
                        step = false;
                    }
                }
            }
        }
        private void searchButton_Click(object sender, EventArgs e)
        {

            if (memDataGridView[0, 0].Value != null)
            {
                string temp = memDataGridView[0, 0].Value.ToString();
                int x = int.Parse(temp);
                memDataGridView[1, 0].Value = app.memory[x];
            }
        }
        private void addButton_Click(object sender, EventArgs e)
        {
            if (memDataGridView[0, 0].Value != null && memDataGridView[1, 0].Value != null)
            {
                string temp = memDataGridView[0, 0].Value.ToString();
                int x = int.Parse(temp);
                temp = memDataGridView[1, 0].Value.ToString();
                int y = int.Parse(temp);
                app.memory[x] = y;
            }
        }
        private void Setup()
        {
            this.SuspendLayout();
            this.Size = new Size(800, 800);
            this.dataGridViewLayout(istrDataGridView, 50, 30, 50, 6, 10);
            string[] istrStr = { "Instruct", "Type", "Dest", "SrcA", "SrcB", "Valid" };
            setDataGridViewName(istrDataGridView, istrStr, 6);

            this.dataGridViewLayout(regDataGridView, 380, 30, 50, 5, 8);
            string[] regStr = { "Reg", "Busy", "Station", "Value", "Valid" };
            setDataGridViewName(regDataGridView, regStr, 5);

            this.dataGridViewLayout(memDataGridView, 400, 245, 100, 2,2);
            string[] memStr = { "MemAddr", "Value" };
            setDataGridViewName(memDataGridView, memStr, 2);

            this.dataGridViewLayout(preRegDataGridView, 50, 320, 70, 4, 6);
            string[] preRegStr = { "PreReg", "Reg", "Value", "Valid" };
            setDataGridViewName(preRegDataGridView, preRegStr, 4);

            this.dataGridViewLayout(afterRegDataGridView, 360, 320, 70, 5, 6);
            string[] afterRegStr = { "AfterReg", "Reg", "Value", "Station", "Valid" };
            setDataGridViewName(afterRegDataGridView, afterRegStr, 5);

            this.dataGridViewLayout(addStDataGridView, 50, 500, 65, 10, 3);
            string[] addDataStr = { "Adder", "Station1", "Reg1", "Value1", "Station2", "Reg2", "Value2", "State/Valid", "Type", "Result" };
            setDataGridViewName(addStDataGridView, addDataStr, 10);

            this.dataGridViewLayout(mulStDataGridView, 50, 620, 65, 10, 2);
            string[] mulDataStr = { "Multiplier", "Station1", "Reg1", "Value1", "Station2", "Reg2", "Value2", "State/Valid", "Type", "Result" };
            setDataGridViewName(mulStDataGridView, mulDataStr, 10);

            this.Controls.Add(startButton);
            startButton.Text = "Start";
            startButton.Location = new Point(670, 70);
            startButton.Click += new EventHandler(startButton_Click);

            this.Controls.Add(cleanButton);
            cleanButton.Text = "Clean";
            cleanButton.Location = new Point(670, 110);
            cleanButton.Click += new EventHandler(cleanButton_Click);

            this.Controls.Add(searchButton);
            searchButton.Text = "Search";
            searchButton.Location = new Point(670, 250);
            searchButton.Click += new EventHandler(searchButton_Click);

            this.Controls.Add(addButton);
            addButton.Text = "AddMem";
            addButton.Location = new Point(670, 280);
            addButton.Click += new EventHandler(addButton_Click);

            this.Controls.Add(choosePanel);
            choosePanel.Controls.Add(chooseButton1);
            choosePanel.Controls.Add(chooseButton2);
            this.Controls.Add(label1);
            this.Controls.Add(label2);
            this.Controls.Add(state);
            choosePanel.Location = new Point(730, 150);
            chooseButton1.Location = new Point(0, 0);
            chooseButton2.Location = new Point(0, 30);
            label1.Location = new Point(650, 150);
            label2.Location = new Point(650, 180);
            state.Location = new Point(670, 40);
            label1.Text = "Continous";
            label2.Text = "Step-By-Step";
            state.Text = "Timer:End";
            chooseButton1.Click += new EventHandler(chooseButton_Click);
            chooseButton2.Click += new EventHandler(chooseButton_Click);
            searchButton.Click += new EventHandler(searchButton_Click);
        }
    }
    class Tomasulo
    {
        static GUIDialog rootDialog;
        [STAThread]
        public static void Main(string[] args)
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            rootDialog = new GUIDialog();
            rootDialog.StartPosition = FormStartPosition.CenterScreen;
            Application.Run(rootDialog);
        }
    }
}
